﻿using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Linq;
using System.Drawing;
using System.Collections.Generic;

namespace SpielMitMirFinal.Models
{
    public class Bot
    {
        public Map myMap { get; set; }
        public Map opponentsMap { get; set; }
        public int opponentId;
        public int gameId;
        public List<IGShip> myShips = new List<IGShip>();

        private List<Point> suggestedHits;
        private Point firstHit;
        private int consecutiveHits = 0;
        private bool verticalHit = false;

        public Bot()
        {
            opponentsMap = new Map();
            myMap = new Map();
            suggestedHits = new List<Point>();
        }
 
        public bool CheckFiringPosition(Point point)
        {
            if (myMap.board[point.X, point.Y] == 1)
            {
                myMap.board[point.X, point.Y] = 2;
                return true;
            }
            else
            {
                myMap.board[point.X, point.Y] = -1;
                return false;
            }
        }

        public void UpdateImpression(Point point, bool hit)
        {
            if (hit)
            {
                opponentsMap.board[point.X, point.Y] = 2;
                if (consecutiveHits == 0)
                {
                    firstHit = point;
                    consecutiveHits++;
                    if (point.Y - 1 >= 0)
                    {
                        if (opponentsMap.board[point.X, point.Y - 1] == 0)
                        {
                            suggestedHits.Add(new Point(point.X, point.Y - 1));
                        }
                    }
                    if (point.X - 1 >= 0)
                    {
                        if (opponentsMap.board[point.X - 1, point.Y] == 0)
                        {
                            suggestedHits.Add(new Point(point.X - 1, point.Y));
                        }
                    }
                    if (point.Y + 1 < 10)
                    {
                        if (opponentsMap.board[point.X, point.Y + 1] == 0)
                        {
                            suggestedHits.Add(new Point(point.X, point.Y + 1));
                        }
                    }
                    if (point.X + 1 < 10)
                    {
                        if (opponentsMap.board[point.X + 1, point.Y] == 0)
                        {
                            suggestedHits.Add(new Point(point.X + 1, point.Y));
                        }
                    }
                }
                else
                {
                    if (point.X == firstHit.X)
                    {
                        verticalHit = true;
                        suggestedHits = suggestedHits.OrderByDescending(x => x.X == point.X).ToList<Point>();
                    }
                    else
                    {
                        verticalHit = false;
                        suggestedHits = suggestedHits.OrderByDescending(x => x.Y == point.Y).ToList<Point>();
                    }
                }

            }
            else
            {
                if (consecutiveHits != 0)
                {
                    if (point.X == firstHit.X)
                    {
                        verticalHit = false;
                        suggestedHits = suggestedHits.OrderBy(x => x.X == point.X).ToList<Point>();
                    }
                    else
                    {
                        verticalHit = true;
                        suggestedHits = suggestedHits.OrderBy(x => x.Y == point.Y).ToList<Point>();
                    }
                }
                consecutiveHits = 0;
                opponentsMap.board[point.X, point.Y] = -1;
            }
            ReassessOppnonentsBoard();
        }

        public void DrawShips()
        {
            foreach (IGShip ship in myShips)
            {
                foreach (Point point in ship.location)
                {
                    myMap.board[point.X, point.Y] = 1;
                }
            }
        }

        private void ReassessOppnonentsBoard()
        {
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    bool badSpot = false;
                    if (i - 1 >= 0 && i + 1 < 10 && j - 1 >= 0 && j + 1 < 10)
                    {
                        if (opponentsMap.board[i - 1, j] < 0 && opponentsMap.board[i, j - 1] < 0 && opponentsMap.board[i + 1, j] < 0 && opponentsMap.board[i, j + 1] < 0)
                        {
                            badSpot = true;
                        }
                    }
                    if (badSpot)
                    {
                        opponentsMap.board[i, j] = -2;
                    }
                }
            }
        }

        public void PlaceShip(int howmany)
        {
            for (int i = 0; i < howmany; i++)
            {
                IGShip sh = new IGShip();
                Random rand = new Random();
                bool rightvalue = false;
                while (!rightvalue)
                {
                    int hor = rand.Next(0, 2);
                    if (hor == 0)
                    {
                        int hx = rand.Next(0, 10);
                        int hy = rand.Next(0, 10);
                        if (myMap.board[hx, hy] != 0)
                        {
                            i--;
                            break;
                        }
                        else
                        {
                            List<Point> location = new List<Point>();
                            Point head = new Point(hx, hy);
                            if (hx - 2 >= 0)
                            {
                                if (myMap.board[hx - 2, hy] == 0 && (myMap.board[hx - 1, hy] == 0))
                                {
                                    Point buttom = new Point(hx - 2, hy);
                                    Point middle = new Point(hx - 1, hy);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            else if (hx - 1 >= 0)
                            {
                                if (myMap.board[hx - 1, hy] == 0 && (myMap.board[hx + 1, hy] == 0))
                                {
                                    Point buttom = new Point(hx - 1, hy);
                                    Point middle = new Point(hx + 1, hy);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            else if (hx + 2 < 10)
                            {
                                if (myMap.board[hx + 2, hy] == 0 && myMap.board[hx + 1, hy] == 0)
                                {
                                    Point buttom = new Point(hx + 2, hy);
                                    Point middle = new Point(hx + 1, hy);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            sh.location = location;
                        }
                    }
                    else
                    {
                        int hx = rand.Next(0, 10);
                        int hy = rand.Next(0, 10);
                        if (myMap.board[hx, hy] != 0)
                        {
                            i--;
                            break;
                        }
                        else
                        {
                            List<Point> location = new List<Point>();
                            Point head = new Point(hx, hy);
                            if (hy - 2 >= 0)
                            {
                                if (myMap.board[hx, hy - 2] == 0 && (myMap.board[hx, hy - 1] == 0))
                                {
                                    Point buttom = new Point(hx, hy - 2);
                                    Point middle = new Point(hx, hy - 1);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            else if (hy - 1 >= 0)
                            {
                                if (myMap.board[hx, hy - 1] == 0 && (myMap.board[hx, hy + 1] == 0))
                                {
                                    Point buttom = new Point(hx, hy - 1);
                                    Point middle = new Point(hx, hy + 1);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            else if (hy + 2 < 10)
                            {
                                if (myMap.board[hx, hy + 2] == 0 && (myMap.board[hx, hy + 1] == 0))
                                {
                                    Point buttom = new Point(hx, hy + 2);
                                    Point middle = new Point(hx, hy + 1);
                                    location.Add(head);
                                    location.Add(middle);
                                    location.Add(buttom);
                                }
                                else
                                {
                                    i--;
                                    break;
                                }
                            }
                            sh.location = location;
                        }
                    }
                    rightvalue = true;
                    myShips.Add(sh);
                    DrawShips();
                }
            }
        }

        public Point Fire()
        {
            Point target = new Point();
            if (suggestedHits.Count != 0)
            {
                target = suggestedHits.FirstOrDefault();
                suggestedHits.Remove(target);
            }
            else
            {
                Random rand = new Random();
                bool rightvalue = false;
                while (!rightvalue)
                {
                    target.X = rand.Next(0, 10);
                    target.Y = rand.Next(0, 10);
                    if (opponentsMap.board[target.X, target.Y] == 0)
                    {
                        rightvalue = true;
                    }
                }
            }
            return target;
        }
    }
}
